fix: preserve active board selection across store refreshes (#509)#526
fix: preserve active board selection across store refreshes (#509)#526Chris0Jeky merged 2 commits intomainfrom
Conversation
Add activeBoardId to boardState and apply a preserveSelection guard in fetchBoards: only update activeBoardId when there is no current selection or the selected board no longer exists in the refreshed list. Also clear activeBoardId correctly on deleteBoard, falling back to the first remaining board. Prevents polling/SignalR-triggered fetchBoards calls from resetting the visible board to the first item in the returned list.
Five cases: initial load sets selection, repeated fetchBoards preserves user selection, missing board falls back to first, empty list yields null, deleteBoard falls back to remaining board.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Self-Review (Adversarial Pass)Checked: Board deleted mid-session
Checked: Initial load with no prior selection
Checked: All paths that touch activeBoardId reviewed
Checked: Test validates polling scenario specificallyThe key test ("preserves activeBoardId across fetchBoards when selected board still exists") simulates two consecutive Known gap (non-blocking)Demo mode VerdictFix is correct and tests are targeted. Ready to merge once CI is green. |
There was a problem hiding this comment.
Code Review
This pull request introduces an activeBoardId state to the board store to track the currently selected board. It implements a preservation guard to ensure that the user's selection is maintained during data refreshes or polling, only resetting the selection if the active board is no longer present in the list. The logic also handles updating the selection when a board is deleted. Comprehensive unit tests were added to cover various selection scenarios. Feedback was provided to simplify the boolean logic used to verify if a board still exists in the fetched list.
| // refreshed list (e.g. it was deleted). This prevents polling/subscription | ||
| // refreshes from resetting the user's active board to the first item. | ||
| const currentId = state.activeBoardId.value | ||
| const stillExists = currentId !== null && freshBoards.some((b) => b.id === currentId) |
There was a problem hiding this comment.
The check currentId !== null is redundant. If currentId is null, freshBoards.some((b) => b.id === currentId) will correctly return false (assuming board IDs are never null), which leads to the desired behavior of resetting the active board. You can simplify this line by removing the explicit null check.
| const stillExists = currentId !== null && freshBoards.some((b) => b.id === currentId) | |
| const stillExists = freshBoards.some((b) => b.id === currentId) |
Adversarial Review (Independent Pass)Verdict: APPROVE with minor notesFindingsMINOR — Demo mode path skips the selection guard
MINOR — Test comment is misleading (non-blocking) In the "preserves activeBoardId" test: The comment says "must NOT flip back to boardB (now first) OR boardA" — but NOTE — No view ( NOTE — No race condition risk The NOTE —
Categories checked
|
Summary
activeBoardIdtoboardStateas the canonical selection refpreserveSelectionguard infetchBoards: only updatesactiveBoardIdwhen there is no current selection or the selected board no longer exists in the refreshed listactiveBoardIdcorrectly indeleteBoard, falling back to the first remaining boardRoot Cause
Every poll/subscription cycle called
fetchBoards, which unconditionally resetactiveBoardIdto the first board in the returned list. When the API returned boards in a different order, the visible board flipped every few seconds without user input.Fix
Before updating
activeBoardId, check if the current selection still exists in the new board list. Only fall back to the first board when the selection is absent or has been removed.Tests
Five unit tests added to
boardStore.spec.ts:activeBoardIdto first boardfetchBoardspreserves user's selection when board still existsfetchBoardsfalls back to first board when selected board is removedfetchBoardsyieldsnullwhen board list becomes emptydeleteBoardfalls back to remaining board when active board is deletedRisk
Low — guard is purely additive; only changes behaviour when a valid selection already exists. Initial load path is unchanged.